//
//  ZLFloatIconMoveHelper.m
//
//  Created by Jiaozl on 2022/1/10.
//

#import "ZLFloatIconMoveHelper.h"
#import "UIView+ZLAdditional.h"

#import <AudioToolbox/AudioToolbox.h>

@interface ZLFloatIconMoveHelper () <UIGestureRecognizerDelegate>
@property (nonatomic, weak) UIView *moveableView;
@property (nonatomic, weak) UIView *containerView;
@property (nonatomic, assign) CGSize moveableViewSize;
@property (nonatomic, assign) CGSize containerViewSize;

@property (nonatomic, assign) BOOL hasAbsorbedToEdge;///< 当前状态为：吸边
@property (nonatomic, assign) CGPoint startPoint;    ///< 起始位置
@property (nonatomic, strong) NSDate *startTime;     ///< 开始时间
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressGr;
@property (nonatomic, strong) UIPanGestureRecognizer *panGr;

@end

@implementation ZLFloatIconMoveHelper

#pragma mark - Life Cycle

- (instancetype)init {
    self = [super init];
    if (self) {
        self.draggable = YES;
        self.needLongPress =    NO;
        self.autoDock =         YES;
        self.scrollToAdsorbed = YES;
        self.hasAbsorbedToEdge = NO;
        self.edgeInset = UIEdgeInsetsMake(0, 10, 0, 10);
        self.appearPercent = 0.33;
        self.absorbedAlpha = 0.3;
        self.absorbDuration = 0.2;
        self.disAbsorbDuration = 0.5;
    }
    return self;
}

#pragma mark - Public Method

- (void)configMoveableView:(UIView *)moveableView containerView:(UIView *)containerView {
    if (!(moveableView && containerView) ) {
        return ;
    }
    
    self.moveableView = moveableView;
    self.containerView = containerView;

    if (!self.draggable) {
        return;
    }
    
    if (self.needLongPress ) {
        [self.moveableView removeGestureRecognizer:self.panGr];
        [self.moveableView addGestureRecognizer:self.longPressGr];
    } else {
        [self.moveableView removeGestureRecognizer:self.longPressGr];
        [self.moveableView addGestureRecognizer:self.panGr];
    }
}

- (void)beginScroll {
    if (!(self.moveableView && self.scrollToAdsorbed) ) {
        return;
    }
    
    if (self.hasAbsorbedToEdge) {
        return;
    }

    // 当前 centerX 坐标位置
    CGFloat centerX = self.moveableView.layer.presentationLayer.position.x;
    if (self.moveableView.centerX != centerX) { // 上一次显示动画未结束，又开始本次隐藏动画，直接设置目标透明度
        self.moveableView.alpha = self.absorbedAlpha;
    }
    self.moveableView.centerX = centerX;
    [self.moveableView.layer removeAllAnimations];
    
    self.hasAbsorbedToEdge = YES;
    [UIView animateWithDuration:self.absorbDuration delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        self.moveableView.alpha = self.absorbedAlpha;
        switch (self.currentEdgeType) {
            case ZLFloatIconMoveableEdgeTypeLeft:
                self.moveableView.right = self.moveableView.width * self.appearPercent;
                break;
            case ZLFloatIconMoveableEdgeTypeRight:
                self.moveableView.left = self.containerView.bounds.size.width - self.moveableView.width * self.appearPercent;
                break;
            default:
                break;
        }
    } completion:^(BOOL finished) {
    }];
}

- (void)endScroll {
    if (!(self.moveableView && self.scrollToAdsorbed) ) {
        return;
    }
    
    self.hasAbsorbedToEdge = NO;
    [UIView animateWithDuration:self.disAbsorbDuration delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        CGRect frame = self.moveableView.frame;
        switch (self.currentEdgeType) {
            case ZLFloatIconMoveableEdgeTypeLeft:
                self.moveableView.centerX = self.moveableViewSize.width / 2 + self.edgeInset.left;
                break;
            case ZLFloatIconMoveableEdgeTypeRight:
                self.moveableView.centerX = self.containerView.bounds.size.width - frame.size.width / 2 - self.edgeInset.right;
                break;
            default:
                break;
        }
        self.moveableView.alpha = 1;
    } completion:^(BOOL finished) {
    }];
}

#pragma mark - Private Method

- (void)updateSize {
    self.moveableViewSize = self.moveableView.size;
    self.containerViewSize = self.containerView.size;
}

- (void)actionLongPress:(UILongPressGestureRecognizer *)longPressGr {
    switch (longPressGr.state) {
        case UIGestureRecognizerStateBegan: {
            [self updateSize];
            [self playVibrate];
            [self shakeAnimationForView:self.moveableView];
            self.startPoint = [longPressGr locationInView:longPressGr.view];
            self.startTime = [NSDate date];
            [self adjustBegainScale:longPressGr.view];
        }
            break;
        case UIGestureRecognizerStateChanged: {
            CGPoint newPoint = [longPressGr locationInView:longPressGr.view];
            CGFloat deltaX = newPoint.x - self.startPoint.x;
            CGFloat deltaY = newPoint.y - self.startPoint.y;
            longPressGr.view.center = CGPointMake(longPressGr.view.center.x + deltaX, longPressGr.view.center.y + deltaY);
        }
            break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded: {
            [self adjustEndPosition:longPressGr.view];
            [self adjustEndScale:longPressGr.view];
            [self statisticsMoveTime];
        }
            break;
        default:
            break;
    }
}
    
/**
 @brief 统计拖动时长
 */
- (void)statisticsMoveTime {
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.startTime];
    self.moveEndWithDuration ? self.moveEndWithDuration(fabs(timeInterval)) : nil;
}

- (void)adjustBegainScale:(UIView *)panView {
    [UIView animateWithDuration:0.3 animations:^{
        panView.transform = CGAffineTransformMakeScale(1.2, 1.2);
        panView.alpha = 0.7;
    }];
}

- (void)adjustEndScale:(UIView *)panView {
    [UIView animateWithDuration:0.3 animations:^{
        panView.transform = CGAffineTransformIdentity;
        panView.alpha = 1.0;
    }];
}

- (void)actionPan:(UIPanGestureRecognizer *)panGestureRecognizer {
    UIView *panView = panGestureRecognizer.view;
    switch (panGestureRecognizer.state) {
        case UIGestureRecognizerStateBegan: {
            [self updateSize];
            self.startTime = [NSDate date];
        }
            break;
        case UIGestureRecognizerStateChanged: {
            CGPoint translation = [panGestureRecognizer translationInView:panView];
            [panGestureRecognizer setTranslation:CGPointZero inView:panView];
            panView.center = CGPointMake(panView.center.x + translation.x, panView.center.y + translation.y);
        }
            break;
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled: {
            [self adjustEndPosition:panView];
            [self statisticsMoveTime];
        }
            break;
        default:
            break;
    }
}

- (void)adjustEndPosition:(UIView *)panView {
    CGPoint location = panView.center;
    CGFloat centerX = location.x, centerY = location.y;
    
    /// 上下边界
    if (centerY < self.moveableViewSize.height / 2 + self.edgeInset.top) {
        centerY = self.moveableViewSize.height / 2 + self.edgeInset.top;
    }
    
    if (centerY > self.containerViewSize.height - self.moveableViewSize.height / 2 - self.edgeInset.bottom) {
        centerY = self.containerViewSize.height - self.moveableViewSize.height / 2 - self.edgeInset.bottom;
    }

    /// 左右边界
    if (self.autoDock ) {
        if (location.x > (self.containerViewSize.width - self.edgeInset.left - self.edgeInset.right) / 2.f + self.edgeInset.left ) {
            centerX = self.containerViewSize.width - self.moveableViewSize.width / 2 - self.edgeInset.right;
            self.currentEdgeType = ZLFloatIconMoveableEdgeTypeRight;
        } else {
            centerX = self.moveableViewSize.width / 2 + self.edgeInset.left;
            self.currentEdgeType = ZLFloatIconMoveableEdgeTypeLeft;
        }
    } else {
        centerX = MAX(centerX, self.moveableViewSize.width / 2 + self.edgeInset.left);
        centerX = MIN(centerX, self.containerViewSize.width - self.moveableViewSize.width / 2 - self.edgeInset.right);
    }
    
    [UIView animateWithDuration:0.3 animations:^{
        panView.center = CGPointMake(centerX, centerY);
    }];
}

- (void)playVibrate {
    if (@available(iOS 10.0, *)) {
        UIImpactFeedbackGenerator *refreshFeedBack = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
        [refreshFeedBack prepare];
        [refreshFeedBack impactOccurred];
    }
}

/**
 *  抖动效果
 *  @param view 要抖动的view
 */
- (void)shakeAnimationForView:(UIView *)view {
    CALayer *viewLayer = view.layer;
    CGPoint position = viewLayer.position;
    CGPoint x = CGPointMake(position.x + 1, position.y);
    CGPoint y = CGPointMake(position.x - 1, position.y);

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
    [animation setFromValue:[NSValue valueWithCGPoint:x]];
    [animation setToValue:[NSValue valueWithCGPoint:y]];
    [animation setAutoreverses:YES];
    [animation setDuration:.06];
    [animation setRepeatCount:3];
    [viewLayer addAnimation:animation forKey:nil];
}

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([otherGestureRecognizer isKindOfClass:UIPanGestureRecognizer.class]) {
        return YES;
    }
    return NO;
}

#pragma mark - Getter

- (UILongPressGestureRecognizer *)longPressGr {
    if (!_longPressGr) {
        _longPressGr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(actionLongPress:)];
    }
    return _longPressGr;
}

- (UIPanGestureRecognizer *)panGr {
    if (!_panGr) {
        _panGr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(actionPan:)];
        _panGr.delegate = self;
    }
    return _panGr;
}

@end
